package edu.gzhu.guli.core.security;

import org.modelmapper.ModelMapper;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import edu.gzhu.guli.core.entity.Admin;
import edu.gzhu.guli.core.entity.Member;
import edu.gzhu.guli.core.entity.Role;
import edu.gzhu.guli.core.repository.AdminRepository;
import edu.gzhu.guli.core.repository.MemberRepository;

import java.util.Collection;
import java.util.Collections;
import java.util.Optional;

@Service
public class DefaultUserDetailsService implements UserDetailsService {

  private final MemberRepository memberRepository;
  private final AdminRepository adminRepository;
  private final ModelMapper modelMapper;
  
  public DefaultUserDetailsService(MemberRepository memberRepository, AdminRepository adminRepository,
      ModelMapper modelMapper) {
    this.memberRepository = memberRepository;
    this.adminRepository = adminRepository;
    this.modelMapper = modelMapper;
  }

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    int index = username.indexOf(':');
    String kind = username.substring(0, index);
    String realName = username.substring(index + 1);
    Optional<SecurityUser> securityUser = Optional.empty();
    if ("ADMIN".equals(kind)) {
      securityUser = adminRepository.findByUsername(realName).map(this::convertToSecurityUser);
    }
    if ("MEMBER".equals(kind)) {
      securityUser = memberRepository.findByUsernameOrPhone(realName, realName).map(this::convertToSecurityUser);
    }
    return securityUser.orElseThrow(() -> new UsernameNotFoundException("用户名不存在"));
  }

  private SecurityUser convertToSecurityUser(Member member) {
    SecurityUser user = modelMapper.map(member, SecurityUser.class);
    Role role = member.getRole();
    Collection<? extends GrantedAuthority> authorities = Collections
        .singleton(new SimpleGrantedAuthority(role.getName()));
    user.setAuthorities(authorities);
    user.setRole(role.getName());
    return user;
  }

  private SecurityUser convertToSecurityUser(Admin admin) {
    SecurityUser user = modelMapper.map(admin, SecurityUser.class);
    Role role = admin.getRole();
    Collection<? extends GrantedAuthority> authorities = Collections
        .singleton(new SimpleGrantedAuthority(role.getName()));
    user.setAuthorities(authorities);
    user.setRole(role.getName());
    return user;
  }
}
